﻿using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using GalaSoft.MvvmLight.Command;
using Looptribe.Moodlin8.Model;
using Looptribe.Moodlin8.Model.Api;
using Looptribe.WinRT.Toolkit;
using Looptribe.WinRT.Toolkit.Controls;

namespace Looptribe.Moodlin8.ViewModel
{
    public class HubViewModel : LoadingViewModel
    {
        private readonly ObservableCollection<CoursesCourseWrapper> _courses = new ObservableCollection<CoursesCourseWrapper>();
        public ObservableCollection<CoursesCourseWrapper> Courses
        {
            get { return _courses; }
        }

        private readonly ObservableCollection<AssignmentWrapper> _assignments = new ObservableCollection<AssignmentWrapper>();
        public ObservableCollection<AssignmentWrapper> Assignments
        {
            get { return _assignments; }
        }

        private readonly ObservableCollection<AssignmentWrapper> _correctedAssignments = new ObservableCollection<AssignmentWrapper>();
        public ObservableCollection<AssignmentWrapper> CorrectedAssignments
        {
            get { return _correctedAssignments; }
        }

        private readonly ObservableCollection<MonthSelector> _calendarMonths = new ObservableCollection<MonthSelector>();
        public ObservableCollection<MonthSelector> CalendarMonths
        {
            get { return _calendarMonths; }
        }

        private readonly ObservableCollection<ICalendarEvent> _events = new ObservableCollection<ICalendarEvent>();
        public ObservableCollection<ICalendarEvent> Events
        {
            get { return _events; }
        }

        private readonly ObservableCollection<FileWrapper> _uploads = new ObservableCollection<FileWrapper>();
        public ObservableCollection<FileWrapper> Uploads
        {
            get { return _uploads; }
        }

        private readonly ObservableCollection<MessageWrapper> _messages = new ObservableCollection<MessageWrapper>();
        public ObservableCollection<MessageWrapper> Messages
        {
            get { return _messages; }
        }

        private MonthSelector _currentMonth;
        public MonthSelector CurrentMonth
        {
            get { return _currentMonth; }
            set
            {
                if (!Equals(_currentMonth, value))
                {
                    Set(() => CurrentMonth, ref _currentMonth, value);
                    RaisePropertyChanged(() => CurrentMonthDate);
                }
            }
        }

        public DateTime CurrentMonthDate
        {
            get { return _currentMonth.Date; }
        }

        public ICommand GotoCourseCommand { get; private set; }
        public ICommand GotoEnrolledCoursesCommand { get; private set; }

        public ICommand GotoNextAssignmentsCommand { get; private set; }
        public ICommand GotoCorrectedAssignmentsCommand { get; private set; }
        public ICommand GotoAssignmentCommand { get; private set; }

        public ICommand GotoUploadsCommand { get; private set; }
        public ICommand OpenUploadCommand { get; private set; }

        public ICommand GotoDateCommand { get; private set; }

        public ICommand GotoUserMessagesCommand { get; private set; }

        public HubViewModel()
        {
            GotoCourseCommand = new RelayCommand<Course>(ExecuteGotoCourse);
            GotoEnrolledCoursesCommand = new RelayCommand(ExecuteGotoEnrolledCourses);
            GotoNextAssignmentsCommand = new RelayCommand(ExecuteGotoNextAssignments);
            GotoCorrectedAssignmentsCommand = new RelayCommand(ExecuteGotoCorrectedAssignments);
            GotoAssignmentCommand = new RelayCommand<AssignmentWrapper>(ExecuteGotoAssignment);
            GotoUploadsCommand = new RelayCommand(ExecuteGotoUploads);
            OpenUploadCommand = new RelayCommand<FileWrapper>(ExecuteOpenUpload);
            GotoDateCommand = new RelayCommand<DateTime>(ExecuteGotoDate);
            GotoUserMessagesCommand = new RelayCommand<User>(ExecuteGotoUserMessages);

            for (var i = -5; i <= 1; ++i)
                CalendarMonths.Add(new MonthSelector(DateTime.Today.AddMonths(i)));
            CurrentMonth = new MonthSelector(DateTime.Today);
        }

        private void ExecuteGotoCourse(Course course)
        {
            Controller.GotoCourse(course);
        }

        private void ExecuteGotoEnrolledCourses()
        {
            Controller.GotoCourses();
        }

        private void ExecuteGotoNextAssignments()
        {
            Controller.GotoNextAssignments(null);
        }

        private void ExecuteGotoCorrectedAssignments()
        {
            Controller.GotoCorrectedAssignments(null);
        }

        private void ExecuteGotoAssignment(AssignmentWrapper assignment)
        {
            Controller.GotoAssignment(assignment);
        }

        private void ExecuteGotoUserMessages(User user)
        {
            Controller.GotoUserMessages(user);
        }

        private void ExecuteGotoUploads()
        {
            Controller.GotoUploads();
        }

        private async void ExecuteOpenUpload(FileWrapper file)
        {
            await Controller.OpenFileAsync(file.WrappedObject);
        }

        private void ExecuteGotoDate(DateTime date)
        {
            Controller.GotoDate(date);
        }

        public async void LoadContent()
        {
            await Refresh();
        }

        public async override Task Refresh()
        {
            await base.Refresh();

            Courses.Clear();
            Events.Clear();
            CorrectedAssignments.Clear();
            Assignments.Clear();
            Uploads.Clear();
            Messages.Clear();

            IsLoading = true;
            var courses = (await Api.GetEnrolledCoursesAsync(CurrentUser)).Data.ToArray();
            var assignments = (await Api.GetAssignmentsAsync(null)).Data;
            var filesResponse = (await Api.GetFilesAsync()).Data;
            var messages = (await Api.GetMessagesAsync()).Data.ToArray();
            var events = (await Api.GetEventsAsync(DateTime.Now.AddMonths(-7), DateTime.Now.AddMonths(1))).Data;
            IsLoading = false;

            if (courses != null)
                Courses.AddMany(courses.Select(a => new CoursesCourseWrapper(a)));
            if (assignments != null)
                foreach (var wrapper in assignments
                    .OrderBy(a => a.DueDate.HasValue ? a.DueDate.Value : DateTime.MaxValue)
                    .Select(assignment => new AssignmentWrapper(assignment, courses.First(a => a.Id == assignment.Course))))
                {
                    if (wrapper.WrappedObject.IsCorrected)
                        CorrectedAssignments.Add(wrapper);
                    else
                    {
                        if (wrapper.WrappedObject.DueDate.HasValue && wrapper.WrappedObject.DueDate >= DateTime.Now)
                            Assignments.Add(wrapper);
                    }
                }
            if (filesResponse != null && filesResponse.Files != null)
                Uploads.AddMany(filesResponse.Files.Where(a => !a.IsDir).Select(a => new FileWrapper(a)).Take(8));

            if (messages != null)
                Messages.AddMany(messages.Select(msg => new MessageWrapper(msg)).Take(6));

            if (events != null)
                Events.AddMany(events.Select(e => new EventWrapper(e)));
        }
    }
}
